package com.soap.service.impl;

import cn.hutool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.soap.commons.ReturnCommons;
import com.soap.entity.po.Goods;
import com.soap.entity.query.GoodsQuery;
import com.soap.feign.service.MSBusinessServiceFeign;
import com.soap.service.GoodsSearchService;

import com.soap.utils.HtmlParseUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by ZhangPY on 2021/1/24
 * Belong Organization OVERUN-9299
 * overun9299@163.com
 * Explain: GoodsSearchServiceImpl
 */
@Slf4j
@Service
public class GoodsSearchServiceImpl implements GoodsSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private HtmlParseUtils htmlParseUtils;

    @Autowired
    private MSBusinessServiceFeign msBusinessServiceFeign;

    @Value("${elasticsearch.businessIndicesGoods}")
    private String businessIndicesGoods;

    @Override
    public String getJDInfoToES(String keyWord) {

        try {
            /** 判断是否存在索引 **/
            GetIndexRequest java_test = new GetIndexRequest(businessIndicesGoods);
            boolean exists = restHighLevelClient.indices().exists(java_test, RequestOptions.DEFAULT);
            if (!exists) {
                /** 创建索引请求 **/
                CreateIndexRequest jd_goods = new CreateIndexRequest(businessIndicesGoods);
                /** 客户端执行请求 indicesClient，请求后获得响应 **/
                CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(jd_goods, RequestOptions.DEFAULT);
                /** 得到响应 */
                boolean acknowledged = createIndexResponse.isAcknowledged();

                if (!acknowledged) {
                    return ReturnCommons.getFail("不存在此es库");
                }
            }
            /** 爬取京东数据 **/
            List<Goods> jdHtmlInfo = htmlParseUtils.getJDHtmlInfo(keyWord);

            if (jdHtmlInfo.size() > 0) {
                /** 批量插入数据 **/
                msBusinessServiceFeign.batchAddGoods(JSONObject.toJSONString(jdHtmlInfo));

                /** 批量请求对象 **/
                BulkRequest request = new BulkRequest();
                /** 批量请求 **/
                for (Goods goods : jdHtmlInfo) {
                    request.add(new IndexRequest(businessIndicesGoods).source(JSONObject.toJSONString(goods), XContentType.JSON));
                }
                /** 发送请求 **/
                BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
            }

            return ReturnCommons.getSuccess("爬虫成功");
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return ReturnCommons.getFail();
    }


    @Override
    public String queryESGoodsList(GoodsQuery goodsQuery) {

        List<Map> searchList = new ArrayList<>();

        try {
            SearchRequest goodsSR = new SearchRequest(businessIndicesGoods);
            /** 构建搜索条件 **/
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            if (goodsQuery.getPage() == null) {
                goodsQuery.setPage(0);
            }
            if (goodsQuery.getLimit() == null) {
                goodsQuery.setLimit(20);
            }
            /** 设置分页 **/
            searchSourceBuilder.from(goodsQuery.getPage());
            searchSourceBuilder.size(goodsQuery.getLimit());

            /** 设置高亮 **/
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title");
            highlightBuilder.preTags("<span style='color:red'>");
            highlightBuilder.postTags("</span>");
            searchSourceBuilder.highlighter(highlightBuilder);
            /** 查询条件，我么可以使用QueryBuilders工具来实现 **/
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", goodsQuery.getKeyWord());
            searchSourceBuilder.query(matchQueryBuilder);
            /** 放入查询体 **/
            goodsSR.source(searchSourceBuilder);

            SearchResponse search = restHighLevelClient.search(goodsSR, RequestOptions.DEFAULT);

            for (SearchHit hit : search.getHits().getHits()) {
                /** 取出高亮字段 */
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                /** 获取结果map **/
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();

                if(highlightFields!=null){
                    /** 取出name高亮字段 */
                    HighlightField nameHighlightField = highlightFields.get("title");
                    if(nameHighlightField!=null){
                        /** 去除内容，此处为一段一段的，所以后面要拼接 */
                        Text[] fragments = nameHighlightField.getFragments();
                        StringBuffer stringBuffer = new StringBuffer();
                        for(Text text:fragments){
                            stringBuffer.append(text);
                        }
                        sourceAsMap.put("title" , stringBuffer.toString());
                    }
                }
                searchList.add(sourceAsMap);
            }

        } catch (Exception e) {
            log.error(e.getMessage());
        }


        return ReturnCommons.getSuccess(searchList);
    }
}
